﻿namespace TestTool.Tests.Common.TestEngine
{
    using ONVIFRTSPFilter;
    using QuartzTypeLib;
    using System;
    using System.Collections;
    using System.Diagnostics;
    using System.IO;
    using System.Runtime.InteropServices;
    using System.Text;
    using System.Threading;
    using TestTool.Tests.Definitions.Exceptions;
    using TestTool.Tests.Definitions.Interfaces;

    public class VideoContainer : IVideoForm
    {
        private string[] activeFilters;
        private string address;
        private int AssumeHeight;
        private int AssumeTimeout;
        private int AssumeWidth;
        private string audioCodecName;
        private bool base64LineBreaks;
        private bool checkActualResolution;
        private bool checkJPEGExtension;
        private string customPauseFields;
        private string customPlayFields;
        private string customSetupFields;
        private bool debugPage;
        private bool doSetupOnReplay = true;
        private IVideoFormEvent EventConsumer;
        private bool FileValid;
        private FilgraphManager FilterGraph;
        private int httpport;
        private bool InStep;
        private bool keepAliveOptions;
        private Hashtable KnownCodecs;
        private IMediaControl MediaControl;
        private bool multicast;
        private string multicastAddress;
        private string multicastAddressAudio;
        private string multicastMultipleSetup;
        private int multicastRtpPortAudio;
        private int multicastRtpPortVideo;
        private int multicastTTL;
        private int nicIndex;
        private string omsdFileName;
        private string password;
        private bool proceedAudio;
        private bool proceedMetadata;
        private bool proceedOptions;
        private bool proceedParameter;
        private bool proceedSyncPoint;
        private bool proceedVideo = true;
        private int replayMaxDuration;
        private bool replayMode;
        private int replayPauseWait;
        private bool replayReverse;
        private bool rtsp = true;
        private ContainerState State;
        private const int step_CheckOptions = 3;
        private const int step_Constructed = 0;
        private const int step_DESCRIBE = 4;
        private const int step_End = 13;
        private const int step_HaltEnvironment = 12;
        private const int step_InitEnvironment = 1;
        private const int step_OpenStream = 5;
        private const int step_OPTIONS = 2;
        private const int step_PAUSE = 9;
        private const int step_PLAY = 7;
        private const int step_SETUP = 6;
        private const int step_StopThread = 10;
        private const int step_TEARDOWN = 11;
        private const int step_WaitStream = 8;
        private string[] StepNames = new string[] { "Constructed", "Init Environment", "OPTIONS", "Check Options", "DESCRIBE", "Open Stream", "SETUP", "PLAY", "Wait Stream", "PAUSE", "Stop Thread", "TEARDOWN", "Halt Environment" };
        private WaitHandle stopEvent = new ManualResetEvent(false);
        private bool tcp;
        private ITestControl TestControl;
        private string user;
        private string videoCodecName;
        private int videoFPS;
        private IVideoWindow VideoWindow;
        private const int WS_BORDER = 0x800000;
        private const int WS_CHILD = 0x40000000;
        private const int WS_CLIPCHILDREN = 0x2000000;
        private const int WS_DLGFRAME = 0x400000;
        private const int WS_EX_APPWINDOW = 0x40000;
        private const int WS_EX_TOOLWINDOW = 0x80;
        private const int WS_MAXIMIZEBOX = 0x10000;
        private const int WS_MINIMIZEBOX = 0x20000;
        private const int WS_NORWALWINDOW = 0xf0000;
        private const int WS_SYSMENU = 0x80000;
        private const int WS_THICKFRAME = 0x40000;
        private const int WS_TOOLWINDOW = 0x400000;

        public VideoContainer()
        {
            Hashtable hashtable = new Hashtable();
            hashtable.Add("ffdshow Video Decoder", new CodecData(CodecType.VideoDecoder, CodecState.Recommended));
            hashtable.Add("ffdshow Audio Decoder", new CodecData(CodecType.AudioDecoder, CodecState.Recommended));
            hashtable.Add("Default DirectSound Device", new CodecData(CodecType.AudioRenderer, CodecState.Recommended));
            hashtable.Add("Video Renderer", new CodecData(CodecType.VideoRenderer, CodecState.Recommended));
            hashtable.Add("MJPEG Decompressor", new CodecData(CodecType.VideoDecoder, CodecState.Known));
            hashtable.Add("Color Space Converter", new CodecData(CodecType.VideoProcessor, CodecState.Known));
            hashtable.Add("AXIS AAC Audio Decoder", new CodecData(CodecType.AudioDecoder, CodecState.Known));
            hashtable.Add("AXIS H.264 Video Decoder", new CodecData(CodecType.VideoDecoder, CodecState.Known));
            hashtable.Add("MainConcept AVC/H.264 Video Decoder", new CodecData(CodecType.VideoDecoder, CodecState.Known));
            hashtable.Add("Microsoft DTV-DVD Video Decoder", new CodecData(CodecType.VideoDecoder, CodecState.Known));
            hashtable.Add("Microsoft DTV-DVD Audio Decoder", new CodecData(CodecType.AudioDecoder, CodecState.Known));
            hashtable.Add("AVI Decompressor", new CodecData(CodecType.VideoProcessor, CodecState.Unrecommended));
            this.KnownCodecs = hashtable;
        }

        public void Clear()
        {
            this.Clear(true);
        }

        public void Clear(bool doStop)
        {
            if (doStop)
            {
                this.Stop();
            }
            if (this.VideoWindow != null)
            {
                this.VideoWindow.Visible = 0;
            }
            this.FileValid = false;
            this.TestControl = null;
            this.MediaControl = null;
            this.VideoWindow = null;
            try
            {
                if (this.FilterGraph != null)
                {
                    Marshal.ReleaseComObject(this.FilterGraph);
                }
            }
            catch (Exception)
            {
            }
            this.FilterGraph = null;
            if (this.omsdFileName != null)
            {
                File.Delete(this.omsdFileName);
                this.FileValid = false;
            }
            this.State = ContainerState.CS_Empty;
        }

        public void CloseWindow()
        {
            this.Clear(true);
        }

        private void Connect()
        {
            if (this.StopEvent == null)
            {
                this.StopEvent = new AutoResetEvent(false);
            }
            Exception ex = null;
            string FN = this.FileName;

            Action func = () =>
            {
                try
                {
                    this.SetSource(FN);
                }
                catch (Exception exception)
                {
                    ex = exception;
                }
            };

            IAsyncResult result = func.BeginInvoke(null, null);
            this.ProceedAction(1, 5, result, ref ex);
            this.StepCodecsCheck();
        }

        private void CreateFile()
        {
            if (!this.FileValid)
            {
                if (this.omsdFileName != null)
                {
                    File.Delete(this.omsdFileName);
                    this.omsdFileName = null;
                }
                StringBuilder builder = new StringBuilder();
                builder.AppendLine("[Test Options]");
                builder.AppendLine(string.Format("Address = \"{0}\"", this.address));
                if (this.user != null)
                {
                    builder.AppendLine(string.Format("User = \"{0}\"", this.user));
                }
                if (this.password != null)
                {
                    builder.AppendLine(string.Format("Password = \"{0}\"", this.password));
                }
                builder.AppendLine(string.Format("UseTCPTunnel = {0}", this.tcp ? 1 : 0));
                builder.AppendLine(string.Format("TunnelPortNumber = {0}", this.httpport));
                builder.AppendLine(string.Format("VideoWidth = {0}", this.AssumeWidth));
                builder.AppendLine(string.Format("VideoHeight = {0}", this.AssumeHeight));
                builder.AppendLine(string.Format("UseAudio = {0}", this.proceedAudio ? 1 : 0));
                builder.AppendLine(string.Format("Timeout = {0}", this.AssumeTimeout));
                builder.AppendLine(string.Format("UseOptions = {0}", this.proceedOptions ? 1 : 0));
                builder.AppendLine(string.Format("UseKeepAlive = {0}", this.proceedParameter ? 1 : 0));
                builder.AppendLine(string.Format("UseKeepAliveOptions = {0}", this.keepAliveOptions ? 1 : 0));
                builder.AppendLine(string.Format("UseMetadata = {0}", this.proceedMetadata ? 1 : 0));
                builder.AppendLine(string.Format("Multicast = {0}", this.multicast ? 1 : 0));
                builder.AppendLine(string.Format("UseVideo = {0}", this.proceedVideo ? 1 : 0));
                builder.AppendLine(string.Format("RTSP = {0}", this.rtsp ? 1 : 0));
                builder.AppendLine(string.Format("VideoFPS = {0}", this.videoFPS));
                builder.AppendLine(string.Format("VideoCodecName = \"{0}\"", this.videoCodecName));
                builder.AppendLine(string.Format("AudioCodecName = \"{0}\"", this.audioCodecName));
                builder.AppendLine(string.Format("MulticastAddress = \"{0}\"", this.multicastAddress));
                builder.AppendLine(string.Format("MulticastAddressAudio = \"{0}\"", this.multicastAddressAudio));
                builder.AppendLine(string.Format("MulticastRtpPortVideo = {0}", this.multicastRtpPortVideo));
                builder.AppendLine(string.Format("MulticastRtpPortAudio = {0}", this.multicastRtpPortAudio));
                builder.AppendLine(string.Format("MulticastTTL = {0}", this.multicastTTL));
                builder.AppendLine(string.Format("Base64LineBreaks = {0}", this.base64LineBreaks ? 1 : 0));
                builder.AppendLine(string.Format("NICIndex = {0}", this.nicIndex));
                builder.AppendLine(string.Format("CustomSetupFields = \"{0}\"", this.customSetupFields));
                builder.AppendLine(string.Format("CustomPlayFields = \"{0}\"", this.customPlayFields));
                builder.AppendLine(string.Format("CustomPauseFields = \"{0}\"", this.customPauseFields));
                builder.AppendLine(string.Format("DoSetupOnReplay = {0}", this.doSetupOnReplay ? 1 : 0));
                builder.AppendLine(string.Format("ReplayMode = {0}", this.replayMode ? 1 : 0));
                builder.AppendLine(string.Format("ReplayMaxDuration = {0}", this.replayMaxDuration));
                builder.AppendLine(string.Format("ReplayPauseWait = {0}", this.replayPauseWait));
                builder.AppendLine(string.Format("ReplayReverse = {0}", this.replayReverse ? 1 : 0));
                builder.AppendLine(string.Format("MulticastMultipleSetup = \"{0}\"", this.multicastMultipleSetup));
                builder.AppendLine(string.Format("CheckActualResolution = {0}", this.checkActualResolution ? 1 : 0));
                builder.AppendLine(string.Format("CheckJPEGExtension = {0}", this.checkJPEGExtension ? 1 : 0));
                this.omsdFileName = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName() + ".omsd");
                StreamWriter writer = new StreamWriter(this.omsdFileName);
                writer.Write(builder.ToString());
                writer.Close();
                this.FileValid = true;
            }
        }

        private void DoCommand(bool condition, Action commandAction, int stepFrom, int stepTo, Action successAction, ContainerState successState, int stepToSetState)
        {
            Exception ex;
            if (condition)
            {
                if ((this.TestControl == null) || (this.MediaControl == null))
                {
                    throw new VideoException("Internal error in AV engine");
                }
                ex = null;
                Action action = delegate
                {
                    try
                    {
                        commandAction();
                    }
                    catch (Exception exception)
                    {
                        ex = exception;
                    }
                };
                OMSDIO ini = new OMSDIO(this.omsdFileName);
                ini.WriteString("Test State", "StepEnded", "0");
                ini.GetMessageCount();
                int num = 0;
                int index = stepFrom;
                int num3 = 0;
                int msgFrom = ini.GetMessageCount() + 1;
                IAsyncResult result = action.BeginInvoke(null, null);
                try
                {
                    bool flag = false;
                    DateTime time = DateTime.Now.AddSeconds((double)(this.Timeout / 0x3e8));
                    if (this.EventConsumer != null)
                    {
                        this.EventConsumer.FireBeginStep(this.StepNames[index]);
                        while (((num3 != stepTo) && (index <= stepTo)) && (DateTime.Now < time))
                        {
                            if (this.StopEvent.WaitOne(0))
                            {
                                throw new StopEventException();
                            }
                            num3 = ini.ReadInt("Test State", "StepEnded", 0);
                            num = Math.Min(Math.Abs(num3), stepTo);
                            while (index < num)
                            {
                                this.LogOutput(ref msgFrom, ini, index);
                                this.EventConsumer.FireStepPassed();
                                this.EventConsumer.FireBeginStep(this.StepNames[++index]);
                            }
                            if (num != index)
                            {
                                Thread.Sleep(100);
                                this.LogOutput(ref msgFrom, ini, index);
                            }
                            else
                            {
                                this.LogOutput(ref msgFrom, ini, index);
                                if (num3 > 0)
                                {
                                    this.EventConsumer.FireStepPassed();
                                }
                                if (num3 < 0)
                                {
                                    string str;
                                    this.GetErrorDescription(out str);
                                    throw new VideoException(str);
                                }
                                if (index < stepTo)
                                {
                                    this.EventConsumer.FireBeginStep(this.StepNames[++index]);
                                }
                            }
                        }
                    }
                    else
                    {
                        flag = 0 == WaitHandle.WaitAny(new WaitHandle[] { this.StopEvent, result.AsyncWaitHandle }, this.Timeout);
                    }
                    if (flag || this.StopEvent.WaitOne(0))
                    {
                        throw new StopEventException();
                    }
                    if (!result.IsCompleted)
                    {
                        throw new VideoException("Connection Timeout");
                    }
                    if (ex != null)
                    {
                        if (!this.InStep && (this.EventConsumer != null))
                        {
                            this.EventConsumer.FireBeginStep("Verifying connection state");
                        }
                        throw ex;
                    }
                }
                catch (StopEventException exception)
                {
                    this.Clear();
                    throw exception;
                }
                catch (Exception exception2)
                {
                    if ((num > stepToSetState) || ((num == stepToSetState) && (num3 > 0)))
                    {
                        this.State = successState;
                    }
                    if (exception2.Message == "Error HRESULT E_FAIL has been returned from a call to a COM component.")
                    {
                        throw new Exception("Operation failed");
                    }
                    throw exception2;
                }
                successAction();
                this.State = successState;
            }
        }

        ~VideoContainer()
        {
            this.Clear();
        }

        private bool GetErrorDescription(out string Error)
        {
            Error = "Internal error";
            OMSDIO ini = new OMSDIO(this.FileName);
            int FailStep = ini.GetCurrentStep();
            string str = string.Empty;
            Action<string> action = delegate (string log)
            {
                int messageOfs = ini.GetMessageOfs(FailStep);
                int num2 = ini.GetMessageOfs(FailStep + 1);
                for (int j = messageOfs; j < num2; j++)
                {
                    string message = ini.GetMessage(j);
                    if (!string.IsNullOrEmpty(message))
                    {
                        if (log != null)
                        {
                            log.Insert(log.Length, '\n' + message);
                        }
                        else
                        {
                            this.EventConsumer.FireLogStepEvent(message);
                        }
                    }
                }
            };
            string str2 = ini.ReadString("Test State", "LastError", string.Empty);
            if (!string.IsNullOrEmpty(str2))
            {
                action(null);
                Error = str2;
                return true;
            }
            if (FailStep != 0)
            {
                int failBits = ini.GetFailBits();
                FailStep = 0;
                while (((failBits & (((int)1) << FailStep)) == 0) && (FailStep < 12))
                {
                    FailStep++;
                }
                if (FailStep >= 12)
                {
                    return false;
                }
            }
            switch (FailStep)
            {
                case 0:
                    Error = "RTSP filter not found, please check your installation";
                    break;

                case 1:
                    Error = "RTSP filter internal error, initialization failed";
                    break;

                case 2:
                    Error = "OPTIONS command error, please check your connection";
                    break;

                case 3:
                    Error = "OPTIONS validation error";
                    break;

                case 4:
                    Error = "DESCRIBE command error, please check your connection";
                    break;

                case 5:
                    Error = "No known media sources found";
                    break;

                case 6:
                    Error = "SETUP command error";
                    break;

                case 7:
                    Error = "PLAY command error";
                    break;

                case 8:
                    Error = "No media frames within timeout, please check your connection";
                    break;

                case 9:
                    Error = "PAUSE command error";
                    break;

                case 10:
                    Error = "RTSP filter internal error - race conditions";
                    break;

                case 11:
                    Error = "TEARDOWN command error";
                    break;

                case 12:
                    Error = "RTSP filter internal error - finalization failed";
                    break;
            }
            Error = Error + str;
            return true;
        }

        public string GetEvents()
        {
            string stepName = null;
            try
            {
                this.TestControl.GetEvents(ref stepName);
            }
            catch (Exception)
            {
            }
            return stepName;
        }

        public bool LogActivity(int Timeout, int FromStep, int ToStep, IAsyncResult Result)
        {
            this.InStep = false;
            DateTime time = DateTime.Now.AddSeconds((double)(Timeout / 0x3e8));
            OMSDIO ini = new OMSDIO(this.omsdFileName);
            while ((ini.GetCurrentStep() < FromStep) && (DateTime.Now < time))
            {
                if (this.StopEvent.WaitOne(0))
                {
                    throw new StopEventException();
                }
                Thread.Sleep(100);
            }
            this.EventConsumer.FireBeginStep(this.StepNames[FromStep]);
            this.InStep = true;
            int step = FromStep;
            int messageOfs = ini.GetMessageOfs(step);
            while (!Result.IsCompleted && (DateTime.Now < time))
            {
                if (this.StopEvent.WaitOne(0))
                {
                    throw new StopEventException();
                }
                this.RollActivityPart(ref ini, ref messageOfs, ref step, ToStep);
                Thread.Sleep(1);
            }
            if (Result.IsCompleted && (ToStep <= ini.GetCurrentStep()))
            {
                while (step <= ToStep)
                {
                    if (!this.RollActivityPart(ref ini, ref messageOfs, ref step, ToStep))
                    {
                        break;
                    }
                    Thread.Sleep(1);
                }
            }
            return (step >= ToStep);
        }

        private void LogCodecState(string Name)
        {
            if (!this.KnownCodecs.ContainsKey(Name))
            {
                this.EventConsumer.FireLogStepEvent("Unknown filter used [" + Name + "], please report to tech support");
            }
            else
            {
                CodecData data = this.KnownCodecs[Name] as CodecData;
                string message = "";
                switch (data.State)
                {
                    case CodecState.Recommended:
                        message = message + "Recommended";
                        break;

                    case CodecState.Known:
                        message = message + "Known";
                        break;

                    case CodecState.Unrecommended:
                        message = message + "Unrecommended";
                        break;
                }
                message = message + " ";
                switch (data.Type)
                {
                    case CodecType.Source:
                        message = message + "Source";
                        break;

                    case CodecType.VideoDecoder:
                        message = message + "Video Decoder";
                        break;

                    case CodecType.AudioDecoder:
                        message = message + "Audio Decoder";
                        break;

                    case CodecType.VideoRenderer:
                        message = message + "Video Renderer";
                        break;

                    case CodecType.AudioRenderer:
                        message = message + "Audio Renderer";
                        break;

                    case CodecType.VideoProcessor:
                        message = message + "Video Processor";
                        break;

                    case CodecType.AudioProcessor:
                        message = message + "Audio Processor";
                        break;
                }
                message = message + " used: " + Name;
                this.EventConsumer.FireLogStepEvent(message);
            }
        }

        private void LogOutput(ref int MsgFrom, OMSDIO Ini, int LogStep)
        {
            int messageOfs = Ini.GetMessageOfs(LogStep + 1);
            if ((messageOfs == 0) || (messageOfs < MsgFrom))
            {
                messageOfs = Ini.GetMessageCount() + 1;
            }
            while (MsgFrom < messageOfs)
            {
                string message = Ini.GetMessage(MsgFrom++);
                if (!string.IsNullOrEmpty(message))
                {
                    this.EventConsumer.FireLogStepEvent(message);
                }
            }
        }

        public void OpenWindow(bool WithAudio)
        {
            this.OpenWindow(WithAudio, true);
        }

        public void OpenWindow(bool WithAudio, bool WithVideo)
        {
            this.UseAudio = WithAudio;
            this.UseVideo = WithVideo;
            this.Connect();
            this.SetupWindow();
            this.Run();
        }

        public void Pause()
        {
            this.DoCommand(this.State == ContainerState.CS_Running, () => this.TestControl.ControlStream(3), 9, 9, () => this.MediaControl.Pause(), ContainerState.CS_Paused, 9);
        }

        public void Play()
        {
            this.DoCommand((((this.State == ContainerState.CS_Connected) || (this.State == ContainerState.CS_Stopped)) || (this.State == ContainerState.CS_Paused)) || (this.State == ContainerState.CS_Running), delegate
            {
                if (this.State != ContainerState.CS_Running)
                {
                    this.MediaControl.Run();
                }
                this.TestControl.ControlStream(1);
            }, ((this.State == ContainerState.CS_Connected) || ((this.State == ContainerState.CS_Stopped) && this.DoSetupOnReplay)) ? 6 : 7, 8, delegate
            {
            }, ContainerState.CS_Running, 6);
        }

        private void ProceedAction(int From, int To, IAsyncResult Result, ref Exception ex)
        {
            try
            {
                bool flag = false;
                if (this.EventConsumer != null)
                {
                    this.LogActivity(this.Timeout, From, To, Result);
                }
                else
                {
                    flag = 0 == WaitHandle.WaitAny(new WaitHandle[] { this.StopEvent, Result.AsyncWaitHandle }, this.Timeout);
                }
                if (flag || this.StopEvent.WaitOne(0))
                {
                    throw new StopEventException();
                }
                if (!Result.IsCompleted)
                {
                    throw new VideoException("Connection Timeout");
                }
                if (ex != null)
                {
                    if (!this.InStep && (this.EventConsumer != null))
                    {
                        this.EventConsumer.FireBeginStep("Verifying connection state");
                    }
                    throw ex;
                }
            }
            catch (StopEventException exception)
            {
                this.Clear(false);
                throw exception;
            }
            catch (Exception exception2)
            {
                string str;
                if (this.GetErrorDescription(out str))
                {
                    throw new VideoException(str);
                }
                if (exception2.Message == "Error HRESULT E_FAIL has been returned from a call to a COM component.")
                {
                    throw new Exception("Operation failed");
                }
                throw exception2;
            }
        }

        public void Replay(Action<Action, Action, Action> actionControl, bool useVideo, bool useAudio, bool useMeta)
        {
            this.UseVideo = useVideo;
            this.UseAudio = useAudio;
            this.EVENTS = useMeta;
            this.Connect();
            this.SetupWindow();
            actionControl(() => this.Play(), () => this.Pause(), () => this.Teardown());
        }

        public void Reset()
        {
            try
            {
                this.Clear(false);
            }
            catch (Exception)
            {
            }
            this.activeFilters = null;
            this.EventConsumer = null;
            this.omsdFileName = null;
            this.FileValid = false;
            this.user = null;
            this.password = null;
            this.address = null;
            this.httpport = 0;
            this.tcp = false;
            this.multicast = false;
            this.proceedOptions = false;
            this.proceedAudio = false;
            this.AssumeWidth = 0;
            this.AssumeHeight = 0;
            this.AssumeTimeout = 0;
            this.proceedParameter = false;
            this.proceedMetadata = false;
            this.proceedSyncPoint = false;
            this.proceedVideo = true;
            this.rtsp = true;
            this.videoFPS = 0;
            this.videoCodecName = null;
            this.audioCodecName = null;
            this.multicastAddress = null;
            this.multicastAddressAudio = null;
            this.multicastRtpPortVideo = 0;
            this.multicastRtpPortAudio = 0;
            this.multicastTTL = 0;
            this.keepAliveOptions = false;
            this.customSetupFields = null;
            this.customPlayFields = null;
            this.customPauseFields = null;
            this.doSetupOnReplay = true;
            this.replayMode = false;
            this.replayMaxDuration = 0;
            this.replayPauseWait = 0;
            this.replayReverse = false;
            this.multicastMultipleSetup = null;
            this.checkActualResolution = false;
            this.checkJPEGExtension = false;
            this.base64LineBreaks = false;
            this.nicIndex = 0;
            this.stopEvent = new ManualResetEvent(false);
            this.debugPage = false;
        }

        private bool RollActivityPart(ref OMSDIO ini, ref int MessID, ref int LogStep, int ToStep)
        {
            if (LogStep <= ToStep)
            {
                if (MessID <= ini.GetMessageCount())
                {
                    string message = ini.GetMessage(MessID);
                    if (!string.IsNullOrEmpty(message))
                    {
                        this.EventConsumer.FireLogStepEvent(message);
                    }
                    MessID++;
                    int messageOfs = ini.GetMessageOfs(LogStep + 1);
                    if ((messageOfs > 0) && (MessID >= messageOfs))
                    {
                        if ((ini.GetFailBits() & (((int)1) << LogStep)) == 0)
                        {
                            this.EventConsumer.FireStepPassed();
                            this.InStep = false;
                        }
                        else
                        {
                            string str2;
                            this.GetErrorDescription(out str2);
                            throw new VideoException(str2);
                        }
                        do
                        {
                            if (this.StopEvent.WaitOne(0))
                            {
                                throw new StopEventException();
                            }
                            LogStep++;
                            messageOfs = ini.GetMessageOfs(LogStep);
                            Thread.Sleep(1);
                        }
                        while ((messageOfs > 0) && (MessID >= messageOfs));
                        LogStep--;
                        if (LogStep <= ToStep)
                        {
                            this.EventConsumer.FireBeginStep(this.StepNames[LogStep]);
                            this.InStep = true;
                        }
                    }
                    return true;
                }
                Thread.Sleep(100);
            }
            return false;
        }

        public void Run()
        {
            Exception ex;
            if ((this.State == ContainerState.CS_Connected) || (this.State == ContainerState.CS_Stopped))
            {
                if ((this.TestControl == null) || (this.MediaControl == null))
                {
                    throw new VideoException("Internal error in AV engine");
                }
                ex = null;

                Action action = () =>
                {
                    try
                    {
                        this.State = ContainerState.CS_Starting;
                        if (this.CheckJPEGExtension || this.CheckActualResolution)
                        {
                            this.MediaControl.Run();
                            this.TestControl.ControlStream(1);
                        }
                        else
                        {
                            this.TestControl.ControlStream(1);
                            this.MediaControl.Run();
                        }
                        this.State = ContainerState.CS_Running;
                    }
                    catch (Exception exception)
                    {
                        ex = exception;
                    }
                };

                IAsyncResult result = action.BeginInvoke(null, null);
                if (this.RTSP)
                {
                    this.ProceedAction(6, 8, result, ref ex);
                }
                else
                {
                    this.ProceedAction(8, 8, result, ref ex);
                }
            }
        }

        private void ScanGraph()
        {
            this.activeFilters = null;
            this.TestControl = null;
            if (this.FilterGraph != null)
            {
                IAMCollection filterCollection = this.FilterGraph.FilterCollection as IAMCollection;
                if (filterCollection != null)
                {
                    int count = filterCollection.Count;
                    if (count <= 0)
                    {
                        this.activeFilters = null;
                    }
                    else
                    {
                        object ppUnk = null;
                        this.activeFilters = new string[count - 1];
                        int index = 0;
                        for (int i = count - 1; i >= 0; i--)
                        {
                            filterCollection.Item(i, out ppUnk);
                            IFilterInfo info = ppUnk as IFilterInfo;
                            if (info.Filter is ITestControl)
                            {
                                this.TestControl = info.Filter as ITestControl;
                            }
                            else
                            {
                                this.activeFilters[index] = info.Name;
                                index++;
                            }
                        }
                    }
                }
            }
        }

        private void SetSource(string FileName)
        {
            try
            {
                this.State = ContainerState.CS_Empty;
                this.FilterGraph = new FilgraphManagerClass();
                try
                {
                    this.FilterGraph.RenderFile(FileName);
                }
                catch (Exception exception)
                {
                    throw ((exception is COMException) ? exception : new COMException(exception.Message));
                }
                this.VideoWindow = this.FilterGraph as IVideoWindow;
                this.MediaControl = this.FilterGraph;
                this.ScanGraph();
                this.State = ContainerState.CS_Connected;
            }
            catch (COMException exception2)
            {
                string error = null;
                Thread.Sleep(0x3e8);
                if (this.GetErrorDescription(out error))
                {
                    throw new VideoException(error);
                }
                throw new VideoException(string.Format("General AV error #{0:X08}, please check MSDN", (uint)exception2.ErrorCode), exception2);
            }
        }

        public void SetupWindow()
        {
            if (this.VideoWindow != null)
            {
                this.VideoWindow.Caption = "ONVIF Video Stream";
                this.VideoWindow.WindowStyle = (this.VideoWindow.WindowStyle & -983041) | 0x400000;
                this.VideoWindow.WindowStyleEx = (this.VideoWindow.WindowStyleEx | 0x80) | 0x40000;
            }
        }

        private void StepCodecsCheck()
        {
            if (this.EventConsumer != null)
            {
                if (this.InStep)
                {
                    this.EventConsumer.FireStepPassed();
                    this.InStep = false;
                }
                this.EventConsumer.FireBeginStep("Checking filters");
                if (this.activeFilters == null)
                {
                    throw new AssertException("No Codecs in graph!");
                }
                foreach (string str in this.activeFilters)
                {
                    this.LogCodecState(str);
                }
                this.EventConsumer.FireStepPassed();
            }
        }

        public void Stop()
        {
            Exception ex;
            if (this.State == ContainerState.CS_Starting)
            {
                this.State = ContainerState.CS_Stopped;
                this.TestControl.ControlStream(2);
                Thread.Sleep(0x3e8);
                this.TestControl.ControlStream(0);
            }
            else if ((this.State == ContainerState.CS_Running) || (this.State == ContainerState.CS_Paused))
            {
                if ((this.TestControl == null) || (this.MediaControl == null))
                {
                    throw new VideoException("Internal error in AV engine");
                }
                ex = null;

                Action action = () =>
                {
                    try
                    {
                        int state = 0;
                        this.State = ContainerState.CS_Stopped;
                        this.VideoWindow.Visible = 0;
                        this.TestControl.GetStreamHealth(ref state);
                        this.TestControl.ControlStream(2);
                        Trace.WriteLine("Trying to close DirectShow " + state.ToString());
                        this.MediaControl.Stop();
                        Trace.WriteLine("DirectShow closed");
                        Thread.Sleep(0x3e8);
                        this.TestControl.ControlStream(0);
                    }
                    catch (Exception exception)
                    {
                        ex = exception;
                    }
                };

                IAsyncResult result = action.BeginInvoke(null, null);
                if (this.RTSP)
                {
                    this.ProceedAction(10, 11, result, ref ex);
                }
                else
                {
                    this.ProceedAction(10, 10, result, ref ex);
                }
            }
        }

        public void Teardown()
        {
            this.DoCommand((this.State == ContainerState.CS_Running) || (this.State == ContainerState.CS_Paused), delegate
            {
                this.VideoWindow.Visible = 0;
                this.TestControl.ControlStream(2);
                this.MediaControl.Stop();
                this.TestControl.ControlStream(0);
            }, 10, 11, () => this.VideoWindow.Visible = 0, ContainerState.CS_Stopped, 11);
        }

        public bool WaitForStableKey(ref double Length)
        {
            try
            {
                this.TestControl.WaitForStableKey(ref Length);
            }
            catch (Exception)
            {
                return false;
            }
            return true;
        }

        public bool WaitForSync(ref int Length)
        {
            try
            {
                this.TestControl.WaitForSync(ref Length);
            }
            catch (Exception)
            {
                return false;
            }
            return true;
        }

        public string Address
        {
            get
            {
                return this.address;
            }
            set
            {
                this.address = value;
                this.FileValid = false;
            }
        }

        public string AudioCodecName
        {
            get
            {
                return this.audioCodecName;
            }
            set
            {
                this.audioCodecName = value;
                this.FileValid = false;
            }
        }

        public bool Base64LineBreaks
        {
            get
            {
                return this.base64LineBreaks;
            }
            set
            {
                this.base64LineBreaks = value;
                this.FileValid = false;
            }
        }

        public bool CheckActualResolution
        {
            get
            {
                return this.checkActualResolution;
            }
            set
            {
                this.checkActualResolution = value;
                this.FileValid = false;
            }
        }

        public bool CheckJPEGExtension
        {
            get
            {
                return this.checkJPEGExtension;
            }
            set
            {
                this.checkJPEGExtension = value;
                this.FileValid = false;
            }
        }

        public string CustomPauseFields
        {
            get
            {
                return this.customPauseFields;
            }
            set
            {
                this.customPauseFields = value;
                this.FileValid = false;
            }
        }

        public string CustomPlayFields
        {
            get
            {
                return this.customPlayFields;
            }
            set
            {
                this.customPlayFields = value;
                this.FileValid = false;
            }
        }

        public string CustomSetupFields
        {
            get
            {
                return this.customSetupFields;
            }
            set
            {
                this.customSetupFields = value;
                this.FileValid = false;
            }
        }

        public bool DebugPage
        {
            get
            {
                return this.debugPage;
            }
            set
            {
                this.debugPage = value;
            }
        }

        public bool DoSetupOnReplay
        {
            get
            {
                return this.doSetupOnReplay;
            }
            set
            {
                this.doSetupOnReplay = value;
                this.FileValid = false;
            }
        }

        public bool EVENTS
        {
            get
            {
                return this.proceedMetadata;
            }
            set
            {
                this.proceedMetadata = value;
                this.FileValid = false;
            }
        }

        public IVideoFormEvent EventSink
        {
            set
            {
                this.EventConsumer = value;
            }
        }

        public string FileName
        {
            get
            {
                this.CreateFile();
                return this.omsdFileName;
            }
        }

        public int HTTPPort
        {
            get
            {
                return this.httpport;
            }
            set
            {
                this.httpport = value;
                this.FileValid = false;
            }
        }

        public bool KEEPALIVE
        {
            get
            {
                return this.proceedParameter;
            }
            set
            {
                this.proceedParameter = value;
                this.FileValid = false;
            }
        }

        public bool Multicast
        {
            get
            {
                return this.multicast;
            }
            set
            {
                this.multicast = value;
                this.FileValid = false;
            }
        }

        public string MulticastAddress
        {
            get
            {
                return this.multicastAddress;
            }
            set
            {
                this.multicastAddress = value;
                this.FileValid = false;
            }
        }

        public string MulticastAddressAudio
        {
            get
            {
                return this.multicastAddressAudio;
            }
            set
            {
                this.multicastAddressAudio = value;
                this.FileValid = false;
            }
        }

        public string MulticastMultipleSetup
        {
            get
            {
                return this.multicastMultipleSetup;
            }
            set
            {
                this.multicastMultipleSetup = value;
                this.FileValid = false;
            }
        }

        public int MulticastRtpPortAudio
        {
            get
            {
                return this.multicastRtpPortAudio;
            }
            set
            {
                this.multicastRtpPortAudio = value;
                this.FileValid = false;
            }
        }

        public int MulticastRtpPortVideo
        {
            get
            {
                return this.multicastRtpPortVideo;
            }
            set
            {
                this.multicastRtpPortVideo = value;
                this.FileValid = false;
            }
        }

        public int MulticastTTL
        {
            get
            {
                return this.multicastTTL;
            }
            set
            {
                this.multicastTTL = value;
                this.FileValid = false;
            }
        }

        public int NICIndex
        {
            get
            {
                return this.nicIndex;
            }
            set
            {
                this.nicIndex = value;
                this.FileValid = false;
            }
        }

        public bool OPTIONS
        {
            get
            {
                return this.proceedOptions;
            }
            set
            {
                this.proceedOptions = value;
                this.FileValid = false;
            }
        }

        public string Password
        {
            get
            {
                return this.password;
            }
            set
            {
                this.password = value;
                this.FileValid = false;
            }
        }

        public int ReplayMaxDuration
        {
            get
            {
                return this.replayMaxDuration;
            }
            set
            {
                this.replayMaxDuration = value;
                this.FileValid = false;
            }
        }

        public bool ReplayMode
        {
            get
            {
                return this.replayMode;
            }
            set
            {
                this.replayMode = value;
                this.FileValid = false;
            }
        }

        public int ReplayPauseWait
        {
            get
            {
                return this.replayPauseWait;
            }
            set
            {
                this.replayPauseWait = value;
                this.FileValid = false;
            }
        }

        public bool ReplayReverse
        {
            get
            {
                return this.replayReverse;
            }
            set
            {
                this.replayReverse = value;
                this.FileValid = false;
            }
        }

        public bool RTSP
        {
            get
            {
                return this.rtsp;
            }
            set
            {
                this.rtsp = value;
                this.FileValid = false;
            }
        }

        public WaitHandle StopEvent
        {
            get
            {
                return this.stopEvent;
            }
            set
            {
                this.stopEvent = value;
                this.FileValid = false;
            }
        }

        public bool SYNC
        {
            get
            {
                return this.proceedSyncPoint;
            }
            set
            {
                this.proceedSyncPoint = value;
                this.FileValid = false;
            }
        }

        public bool TCP
        {
            get
            {
                return this.tcp;
            }
            set
            {
                this.tcp = value;
                this.FileValid = false;
            }
        }

        public int Timeout
        {
            get
            {
                return this.AssumeTimeout;
            }
            set
            {
                this.AssumeTimeout = value;
                this.FileValid = false;
                if (this.AssumeTimeout < 0x7d0)
                {
                    this.AssumeTimeout = 0x7d0;
                }
                if (this.AssumeTimeout > 0x927c0)
                {
                    this.AssumeTimeout = 0x927c0;
                }
            }
        }

        public bool UseAudio
        {
            get
            {
                return this.proceedAudio;
            }
            set
            {
                this.proceedAudio = value;
                this.FileValid = false;
            }
        }

        public bool UseKeepAliveOptions
        {
            get
            {
                return this.keepAliveOptions;
            }
            set
            {
                this.keepAliveOptions = value;
                this.FileValid = false;
            }
        }

        public string User
        {
            get
            {
                return this.user;
            }
            set
            {
                this.user = value;
                this.FileValid = false;
            }
        }

        public bool UseVideo
        {
            get
            {
                return this.proceedVideo;
            }
            set
            {
                this.proceedVideo = value;
                this.FileValid = false;
            }
        }

        public string VideoCodecName
        {
            get
            {
                return this.videoCodecName;
            }
            set
            {
                this.videoCodecName = value;
                this.FileValid = false;
            }
        }

        public int VideoFPS
        {
            get
            {
                return this.videoFPS;
            }
            set
            {
                this.videoFPS = value;
                this.FileValid = false;
            }
        }

        public int VideoHeight
        {
            get
            {
                return this.AssumeHeight;
            }
            set
            {
                this.AssumeHeight = value;
                this.FileValid = false;
            }
        }

        public int VideoWidth
        {
            get
            {
                return this.AssumeWidth;
            }
            set
            {
                this.AssumeWidth = value;
                this.FileValid = false;
            }
        }

        private class CodecData
        {
            public VideoContainer.CodecState State;
            public VideoContainer.CodecType Type;

            public CodecData(VideoContainer.CodecType T, VideoContainer.CodecState S)
            {
                this.Type = T;
                this.State = S;
            }
        }

        private enum CodecState
        {
            Recommended,
            Known,
            Unrecommended
        }

        private enum CodecType
        {
            Source,
            VideoDecoder,
            AudioDecoder,
            VideoRenderer,
            AudioRenderer,
            VideoProcessor,
            AudioProcessor
        }

        private enum ContainerState
        {
            CS_Empty,
            CS_Connected,
            CS_Starting,
            CS_Running,
            CS_Paused,
            CS_Stopped
        }

        private class IniFileClass
        {
            private string IniFile = "";

            public IniFileClass(string IniFile)
            {
                this.IniFile = IniFile;
            }

            [DllImport("kernel32")]
            private static extern int GetPrivateProfileInt(string Section, string Key, int Default, string FilePath);
            [DllImport("kernel32")]
            private static extern int GetPrivateProfileString(string Section, string Key, string Default, StringBuilder retVal, int Size, string FilePath);
            public int ReadInt(string Section, string Key, int Default)
            {
                return GetPrivateProfileInt(Section, Key, Default, this.IniFile);
            }

            public string ReadString(string Section, string Key, string Default)
            {
                StringBuilder retVal = new StringBuilder(0xff);
                GetPrivateProfileString(Section, Key, Default, retVal, 0xff, this.IniFile);
                return retVal.ToString();
            }

            public void WriteInt(string Section, string Key, int Value)
            {
                WritePrivateProfileInt(Section, Key, Value, this.IniFile);
            }

            [DllImport("kernel32")]
            private static extern long WritePrivateProfileInt(string Section, string Key, int Value, string FilePath);
            [DllImport("kernel32")]
            private static extern long WritePrivateProfileString(string Section, string Key, string Value, string FilePath);
            public void WriteString(string Section, string Key, string Value)
            {
                WritePrivateProfileString(Section, Key, Value, this.IniFile);
            }
        }

        private class OMSDIO : VideoContainer.IniFileClass
        {
            private const string ReplyID = "Test State";

            public OMSDIO(string IniFile) : base(IniFile)
            {
            }

            public int GetCurrentStep()
            {
                return base.ReadInt("Test State", "CurrentStep", 0);
            }

            public int GetFailBits()
            {
                return base.ReadInt("Test State", "FailBits", 0);
            }

            public string GetMessage(int Num)
            {
                return base.ReadString("Test State", string.Format("Log{0:d03}", Num), "");
            }

            public int GetMessageCount()
            {
                return base.ReadInt("Test State", "MessageCount", 0);
            }

            public int GetMessageOfs(int Step)
            {
                return base.ReadInt("Test State", string.Format("Step{0:d03}", Step), 0);
            }

            public int GetPassBits()
            {
                return base.ReadInt("Test State", "PassBits", 0);
            }
        }
    }
}

